using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;


namespace SmsServerClient
{
    public struct FILETIME
    {
        public UInt32 dwLowDateTime;
        public UInt32 dwHighDateTime;

        public void FromDateTime(DateTime time)
        {
            Int64 hFT1 = time.ToFileTimeUtc();
            dwLowDateTime = (UInt32)(hFT1 & 0xFFFFFFFF);
            dwHighDateTime = (UInt32)(hFT1 >> 32);
        }
    }
    public struct SystemTime
    {
        public ushort wYear;
        public ushort wMonth;
        public ushort wDayOfWeek;
        public ushort wDay;
        public ushort wHour;
        public ushort wMinute;
        public ushort wSecond;
        public ushort wMilliseconds;

        public void FromDateTime(DateTime time)
        {
            wYear = (ushort)time.Year;
            wMonth = (ushort)time.Month;
            wDayOfWeek = (ushort)time.DayOfWeek;
            wDay = (ushort)time.Day;
            wHour = (ushort)time.Hour;
            wMinute = (ushort)time.Minute;
            wSecond = (ushort)time.Second;
            wMilliseconds = (ushort)time.Millisecond;
        }
    }
    class HelperClass
    {
        public static DateTime FileTime2DateTime(FILETIME ft)
        {
            long hFT2 = (((long)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
            DateTime dte = DateTime.FromFileTimeUtc(hFT2);
            return dte;
        }
            
        public static FILETIME DateTime2FileTime(DateTime dte)
        {
            FILETIME ft = new FILETIME();
            long hFT1 = dte.ToFileTimeUtc();
            ft.dwLowDateTime = (UInt32) (hFT1 & 0xFFFFFFFF);
            ft.dwHighDateTime = (UInt32) (hFT1 >> 32);
            return ft;
        }

        public static string CleanNumber(string Mobile)
        {
            Mobile = Mobile.Trim().ToLower();
            string rstr = "";
            if (Mobile == null || Mobile.Trim().Length == 0)
                return string.Empty;
            for (int i = 0; i < Mobile.Length; i++)
            {
                if (Mobile[i] == '+' || (Mobile[i] >= '0' && Mobile[i] <= '9'))
                    rstr += Mobile[i];
            }
            if (rstr == "" || rstr == "+")
                return string.Empty;
            else
                return rstr;
        }
    }
    public class UnmanagedAPI
    {
        [DllImport("readmsg.dll")]
        public static extern IntPtr MapiLogin(String MsgStore);
        [DllImport("readmsg.dll")]
        public static extern Boolean MapiLogout(IntPtr pMapi);
        [DllImport("readmsg.dll")]
        public static extern Boolean GetNextMessage(IntPtr pMapi, FILETIME lFileTime, StringBuilder mBody, StringBuilder mNumber, ref FILETIME mDateTime, Boolean mDelete);
        [DllImport("mapirule.dll")]
        public static extern bool SmsMessageAvailable(StringBuilder message, StringBuilder phoneNumber, ref FILETIME mDateTime, ref int Count);
        [DllImport("mapirule.dll")]
        public static extern bool CaptureSmsMessages();
        [DllImport("mapirule.dll")]
        public static extern void TerminateSmsMessagePassing();
        [DllImport("mapirule.dll")]
        public static extern bool ChangeCapturingFlag(bool value);
        [DllImport("mapirule.dll")]
        public static extern int DllRegisterServer();
        [DllImport("mapirule.dll")]
        public static extern void DllUnregisterServer();
        [DllImport("coredll.dll")]
        public static extern IntPtr LoadLibrary(string libName);
        [DllImport("coredll.dll")]
        public static extern int FreeLibrary(IntPtr hLibModule);
        [DllImport("coredll.dll")]
        public static extern int GetLastError();


    }
    public class SmsSender
    {
        public SmsSender()
        {
        }
        private const string Sms_MSGTYPE_TEXT = "Microsoft Text SMS Protocol";
        private const int Sms_MODE_SEND = 2;             // Open in send mode
        private const int SmsDE_GSM = 1;                 // Use standard GSM encoding
        private const int SmsAT_UNKNOWN = 0;               //Unknown type of address
        private const int SmsAT_INTERNATIONAL = 1;       // International number format
        private const int PS_MESSAGE_OPTION_NONE = 0;    // No message options
        private const int PS_MESSAGE_CLASS0 = 0;         // Show but do not store
        private const int PS_MESSAGE_CLASS1 = 1;         // Store and show
        private const int PSRO_NONE = 0;                 // No replacements
        private const int Sms_OPTION_DELIVERY_NONE = 0;  // No delivery options
        private const int Sms_MAX_ADDRESS_LENGTH = 128;  // Max length of address

        [DllImport("sms.dll")]
        private static extern int SmsOpen(
            string ptsMessageProtocol,
            int dwMessageModes,
            ref IntPtr psmshHandle,
            int phMessageAvailableEvent);

        [DllImport("sms.dll")]
        private static extern int SmsSendMessage(
            IntPtr smshHandle,
            int psmsaSmsCAddress,
            byte[] psmsaDestinationAddress,
            int pstValidityPeriod,
            byte[] pbData,
            int dwDataSize,
            byte[] pbProviderSpecificData,
            int dwProviderSpecificDataSize,
            int smsdeDataEncoding,
            int dwOptions,
            int psmsmidMessageID);

        [DllImport("sms.dll")]
        private static extern int SmsClose(IntPtr smshHandle);

        public static int SendSms(string Number, string Message)
        {
            int returnValue = 0;
            IntPtr smsHandle = new IntPtr(0);

            // Set address structure
            byte[] smsatAddressType = BitConverter.GetBytes(SmsAT_UNKNOWN);
            byte[] ptsAddress = Encoding.Unicode.GetBytes(Number);
            byte[] smsAddressTag = new byte[smsatAddressType.Length + ptsAddress.Length];
            Array.Copy(smsatAddressType, 0, smsAddressTag, 0, smsatAddressType.Length);
            Array.Copy(ptsAddress, 0, smsAddressTag, smsatAddressType.Length, ptsAddress.Length);

            // Set provider data structure
            byte[] dwMessageOptions = BitConverter.GetBytes(PS_MESSAGE_OPTION_NONE);
            byte[] psMessageClass = BitConverter.GetBytes(PS_MESSAGE_CLASS1);
            byte[] psReplaceOption = BitConverter.GetBytes(PSRO_NONE);
            byte[] smsProviderDataTag = new byte[dwMessageOptions.Length +
                                                    psMessageClass.Length + psReplaceOption.Length];
            Array.Copy(dwMessageOptions, 0, smsProviderDataTag, 0, dwMessageOptions.Length);
            Array.Copy(psMessageClass, 0, smsProviderDataTag, dwMessageOptions.Length,
                                psMessageClass.Length);
            Array.Copy(psReplaceOption, 0, smsProviderDataTag, dwMessageOptions.Length +
                                psMessageClass.Length, psReplaceOption.Length);

            // Set message
            byte[] smsMessageTag = Encoding.Unicode.GetBytes(Message);

            // Get handle
            if (0 != SmsOpen(Sms_MSGTYPE_TEXT, Sms_MODE_SEND, ref smsHandle, 0))
                returnValue = -1; // Could not open

            // Send message
            if (returnValue == 0)
            {
                int temp = 0;
                temp =    SmsSendMessage(smsHandle, 0, smsAddressTag, 0,
                    smsMessageTag, smsMessageTag.Length,
                    smsProviderDataTag, smsProviderDataTag.Length,
                    SmsDE_GSM, Sms_OPTION_DELIVERY_NONE, 0);
                if (temp!=0 )
                    returnValue = -2;
            }

            // Release handle
            if (returnValue == 0 || returnValue == -2)
            {
                if (0 != SmsClose(smsHandle))
                    returnValue = -3; // Could not close
            }
            smsHandle = IntPtr.Zero;
            return returnValue;
        }
    }

}
